{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "fd4d1b56",
   "metadata": {},
   "source": [
    "# 第一章 前提基础"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f215d747",
   "metadata": {},
   "source": [
    "## 一、Blender开发API文档\n",
    "\n",
    "- 新版API： https://docs.blender.org/api/current/index.html\n",
    "- 旧版API： https://archive.blender.org/wiki/index.php/\n",
    "\n",
    "新版本API例子少，旧版例子多但部分API在新版内废止，无法使用"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "99424b6c",
   "metadata": {},
   "source": [
    "## 二、Blender基础模块\n",
    "\n",
    "\n",
    "bpy为blender内置主要7个模块：  \n",
    "- data \n",
    "- context \n",
    "- ops \n",
    "- types \n",
    "- props \n",
    "- utils \n",
    "- path    \n",
    "Blender的七个管理员\n",
    "  \n",
    "bpy    \n",
    "管理所有数据： object ，meshes， materials  \n",
    "注意：由于bpy.context 和 bpy.data 在Blender里很常用  \n",
    "故通常使用C D 两个字母替代  \n",
    "```  C = bpy.context, D = bpy.data ```  \n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b6556629",
   "metadata": {},
   "source": [
    "当然建议每次写插件填入如下加载内容"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "96e92ee2",
   "metadata": {},
   "outputs": [],
   "source": [
    "import bpy\n",
    "from bpy import data as D\n",
    "from bpy import context as C\n",
    "from mathutils import *\n",
    "from math import "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5878f889",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "2d4a7fa3",
   "metadata": {},
   "source": [
    "### 1. 模块 bpy.data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b21e7371",
   "metadata": {},
   "outputs": [],
   "source": [
    "#所有构件的组\n",
    "D.objects  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "566ad447",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 若有部件名称为 Cube 则得到cube实例\n",
    "cube=D.objects['Cube'] "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "24b286c7",
   "metadata": {},
   "outputs": [],
   "source": [
    "#若我需要查看Cube的位置 \n",
    "D.objects['Cube'].location\n",
    "# Vector((0.0, 0.0, 0.0))\n",
    "\n",
    "#若我需要改变Cube的位置到世界坐标(5.1,3.5,8.4)\n",
    "#此处默认单位米 \n",
    "##方式一\n",
    "D.objects['Cube'].location[0] = 5.1\n",
    "D.objects['Cube'].location[1] = 3.5,\n",
    "D.objects['Cube'].location[2] = 8.4\n",
    "##方式二：\n",
    "D.objects['Cube'].location = Vector((5.1,3.5,8.4))\n",
    "\n",
    "#注意 ： 物体实例有些属性为只读，无法编辑"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3645a4dd",
   "metadata": {},
   "outputs": [],
   "source": [
    "#若我要查看 Dots Stroke 的Alpha通道阈值\n",
    "D.materials['Dots Stroke'].alpha_threshold\n",
    "# 0.5\n",
    "\n",
    "#若我要改变 Dots Stroke 的Alpha通道阈值\n",
    "D.materials['Dots Stroke'].alpha_threshold = 0.3"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b7418256",
   "metadata": {},
   "source": [
    "### 2. 模块 bpy.context"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3805ddb8",
   "metadata": {},
   "source": [
    "- context是数据管理的一个全局变量集合，包含了目前被选择激活的物体属性 以及当前物体编辑模式\n",
    "\n",
    "- 只能访问当前激活的area数据，每个窗口都有唯一名称 即为当前面板下对应的窗口，当前操作的窗口\n",
    "\n",
    "- 获得的数据只能readonly ，即context的第一个点后的内容无法修改"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fa53f111",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 显示所有选择的物体  外框橙色的物体\n",
    "C.selected_objects\n",
    "# 显示所有激活的物体  外框黄色的物体 就算被取消选择  类似C.object\n",
    "C.active_object"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "40ee821e",
   "metadata": {},
   "outputs": [],
   "source": [
    "#由于只读，如下代码无法成功运行\n",
    "C.area = 1 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c78626f9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 但是 area内的属性和context无关  故可以修改\n",
    "C.area.ui_type = \"VIEW_3D\" \n",
    "# 运行后 面板会从 当前编辑器面板 跳转到 3D视图面板"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ff2a70a1",
   "metadata": {},
   "outputs": [],
   "source": [
    "#查看当前面板名称\n",
    "C.area.ui_type\n",
    "# 'CONSOLE'  或'VIEW_3D' 或  'TEXT_EDITOR'  等"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "85fb525f",
   "metadata": {},
   "outputs": [],
   "source": [
    "#如果我需要跨域访问其他面板内容 使用scene\n",
    "C.scene.objects['Cube']  "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "699a711d",
   "metadata": {},
   "source": [
    "### 3. 模块 bpy.ops"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8ac34cab",
   "metadata": {},
   "source": [
    "Operators\n",
    "所有的操作指令，如按钮，建模操作，创建、删除模型\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0a670060",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 移动\n",
    "bpy.ops.outliner\n",
    ".item_activate(extend=False, deselect_all=True)\n",
    "# 删除选中的物体\n",
    "bpy.ops.object.delete(use_global=False)\n",
    "# 在游标处创建UV球\n",
    "bpy.ops.mesh\n",
    ".primitive_uv_sphere_add\n",
    "(radius=1, enter_editmode=False, align='WORLD',\n",
    " location=(0, 0, 0), scale=(1, 1, 1))\n",
    "# 编辑模式和物体模式切换\n",
    "bpy.ops.object.editmode_toggle()\n",
    "# 网格细分动作\n",
    "bpy.ops.mesh.subdivide()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "73fddb60",
   "metadata": {},
   "source": [
    "大致功能如此  \n",
    "由于ops比较重要，后期会有更加详细的讲解  "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "af0426e3",
   "metadata": {},
   "source": [
    "### 4. 模块 bpy.types"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f2ce9ea1",
   "metadata": {},
   "source": [
    "所有实现的“class类模板”定义    \n",
    "所有Blender内实现都是继承父类实现"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8b139366",
   "metadata": {},
   "source": [
    "### 5. 模块 bpy.props"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1ca4e699",
   "metadata": {},
   "source": [
    "blender 内 的 properties 属性 管理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "775b02bd",
   "metadata": {},
   "outputs": [],
   "source": [
    "#定义学生类  \n",
    "\n",
    "class student():\n",
    "    \n",
    "    age = 18 \n",
    "    name =\"triangle\"\n",
    "    sex = \"man\"\n",
    "    \n",
    "    def playGame(self):\n",
    "        pass\n",
    "    \n",
    "    def sleep(self):\n",
    "        pass\n",
    "    \n",
    "#关于类的内容是面向对象编程必要的思维 此处不多介绍了"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7107d8e3",
   "metadata": {},
   "source": [
    "#### 作用：  \n",
    "对于现有类结构中的而属性，进行扩充"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5c81a823",
   "metadata": {},
   "source": [
    "#### 属性分两大类\n",
    "- RNA属性\n",
    "- ID属性 \n",
    "\n",
    "\n",
    "在界面中 N --  item -- Properties 下可见id属性"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b8525ef2",
   "metadata": {},
   "source": [
    "#### RNA属性  \n",
    "- 只能对bpy.types模板类的属性扩充  对其他模块无效\n",
    "- 所有的bpy.types模板子类都有该属性  \n",
    "- 需要提前声明  \n",
    "- int float string bool enum  \n",
    "\n",
    "注：  \n",
    "在界面中，RNA属性定义后，有时部分构件不出现该属性，须赋值刷新  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "84066909",
   "metadata": {},
   "outputs": [],
   "source": [
    "#对于property定义参数可查看API文档\n",
    "# 通常含 名称 描述 数值限定 \n",
    "# 并含有三个激活函数 update get set\n",
    "bpy.props.IntProperty\n",
    "bpy.props.FloatProperty\n",
    "bpy.props.StringProperty"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f56b1a18",
   "metadata": {},
   "outputs": [],
   "source": [
    "#实例\n",
    "bpy.data.objects['Cube'].testInt = \n",
    "    bpy.props.IntProperty(\n",
    "        name='test',\n",
    "        default= 22  )  \n",
    "#该代码无法运行  此时未声明testInt属性"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3a308719",
   "metadata": {},
   "outputs": [],
   "source": [
    "#开始定义属性\n",
    "bpy.types.Object.myInt = bpy.props.IntProperty(\n",
    "    name ='test',\n",
    "    max = 10 ,\n",
    "    min = 1,\n",
    "    default = 5\n",
    ")\n",
    "\n",
    "#查看定义的属性\n",
    "C.scene.objects['Cube'].myInt\n",
    "\n",
    "#并修改\n",
    "C.scene.objects['Cube'].myInt = 20\n",
    "#上述得到结果为10   由于定义时确定最大 是10\n",
    "\n",
    "#并修改\n",
    "C.scene.objects['Cube'].myInt = 0\n",
    "#上述得到结果为1    由于定义时确定最小 是1 \n",
    "\n",
    "#由于所有构件继承了Object类构建 \n",
    "#那么场景内其他物体也有RNA属性  故有\n",
    "C.scene.objects['Light'].myInt\n",
    "# 结果为 5 \n",
    "D.objects['Light'].myInt\n",
    "# 结果为 5 \n",
    "D.objects['Camera'].myInt\n",
    "# 结果为 5 \n",
    "\n",
    "#然后常见内新建了其他部件\n",
    "#依旧带有该属性"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1f03ff05",
   "metadata": {},
   "outputs": [],
   "source": [
    "#对mesh定义float属性\n",
    "bpy.types.Mesh.myFloat = bpy.props.FloatProperty(\n",
    "    name ='float',\n",
    "    max = 10.0,\n",
    "    min = 9.0,\n",
    "    default = 1.0\n",
    ")\n",
    "\n",
    "#对mesh定义bool属性\n",
    "bpy.types.Mesh.myBool = bpy.props.BoolProperty(\n",
    "    name ='bool',     \n",
    "    default = False\n",
    ")\n",
    "\n",
    "#查看定义的属性\n",
    "D.meshes['Cube'].myFloat\n",
    "# 1.0\n",
    "D.meshes['Sphere'].myFloat\n",
    "# 1.0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2a20851c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 对场景定义string属性\n",
    "bpy.types.Scene.myString = bpy.props.StringProperty(\n",
    "    name ='string',  \n",
    "    maxlen = 6,\n",
    "    default = 'hello'\n",
    ")\n",
    "\n",
    "#查看定义的属性\n",
    "D.scenes['Scene'].myString\n",
    "# hello"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bdd71a74",
   "metadata": {},
   "source": [
    "#### ID属性  \n",
    "- 对bpy.types模板实例（子类）的属性扩充  \n",
    "- 只有单一实例类才有该属性  \n",
    "- 无需提前声明  \n",
    "- int float string （  没有 bool enum  ）\n",
    "\n",
    "注：  \n",
    "- 属性有时不显示  赋值刷新即可\n",
    "- 在ID属性中bool类型会转为int"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c14e93b4",
   "metadata": {},
   "outputs": [],
   "source": [
    "#创建\n",
    "D.objects['Cube']['idInt'] =1\n",
    "D.objects['Cube']['idFloat'] = 6.0\n",
    "D.objects['Cube']['idString'] ='Id_Prop'\n",
    "\n",
    "#查看\n",
    "D.objects['Cube']['idInt'] \n",
    "# 1\n",
    "D.objects['Cube']['idFloat'] \n",
    "# 6.0\n",
    "\n",
    "#查看\n",
    "D.objects['Sphere']['idInt'] \n",
    "#该代码报错  由于ID属性只能用于一个实例构件"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1794004d",
   "metadata": {},
   "source": [
    "#### 属性删除 "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0956088b",
   "metadata": {},
   "source": [
    "传统如下的删除代码会报错   \n",
    "我们需要采取其他方法删除属性   \n",
    "bpy.props.RemoveProperty\n",
    "\n",
    "界面上显示的RNA属性删除操作：\n",
    "- 删除RNA属性 del RNA -> ID  \n",
    "- 删除ID属性（包括RNA删除后导致出现的ID属性）  del ID"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fb64b54a",
   "metadata": {},
   "outputs": [],
   "source": [
    "#删除RNA属性 使用pyhton中的del功能\n",
    "del bpy.types.Object.myInt\n",
    "#此时myInt由RNA属性转为ID属性"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "83ce3255",
   "metadata": {},
   "outputs": [],
   "source": [
    "#删除属性 使用pyhton中的del功能 \n",
    "del D.objects['Cube']['myInt']  #此处删掉RNA去除后进入ID属性的条目\n",
    "del D.objects['Cube']['idInt']  # 此处删掉ID属性"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9ef10522",
   "metadata": {},
   "source": [
    "#### 工程文件    \n",
    "\n",
    "当RNA在界面显示    \n",
    "RNA属性被删除则会进入ID属性\n",
    "\n",
    "当RNA在界面不显示     \n",
    "则进行删除操作 则会被直接删除\n",
    "\n",
    "#### link blend文件  \n",
    "\n",
    "当RNA在界面显示    \n",
    "RNA属性被删除则会进入ID属性\n",
    "\n",
    "当RNA在界面不显示     \n",
    "则进行删除操作 则会被直接删除"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ebe6235c",
   "metadata": {},
   "source": [
    "##### 脚本编写  少用RNA属性"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "20659671",
   "metadata": {},
   "source": [
    "#### 高级操作 -- 枚举类型"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "12da17cc",
   "metadata": {},
   "source": [
    "枚举类型\n",
    "参数可见API  \n",
    "定义  名称 描述 图标 数字 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "08004963",
   "metadata": {},
   "outputs": [],
   "source": [
    "#定义元组表\n",
    "items = [ \n",
    "    ('RED', 'red', 'this is red', 1),\n",
    "    ('GREEN', 'green', 'this is green', 2),\n",
    "    ('YELLOW', 'yellow', 'this is yellow', 3)\n",
    "]\n",
    "#定义枚举\n",
    "bpy.types.Object.myEnum=bpy.props.EnumProperty(\n",
    "    name = 'enum',\n",
    "    items = items \n",
    ")\n",
    "\n",
    "#查看\n",
    "D.objects['Cube'].myEnum\n",
    "# RED\n",
    "\n",
    "#界面内表现为 下拉框列表\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "739f8575",
   "metadata": {},
   "source": [
    "#### 高级操作 -- 数组类型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "da0821a0",
   "metadata": {},
   "outputs": [],
   "source": [
    "bpy.props.IntVectorProperty()\n",
    "bpy.props.FloatVectorProperty()\n",
    "bpy.props.BoolVectorProperty()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "20b31c44",
   "metadata": {},
   "source": [
    "- 最大尺寸长度为32\n",
    "- 不是容器 list 无法扩充\n",
    "- subtype属性：扩展数组可表达类型的功能"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2dfa5246",
   "metadata": {},
   "outputs": [],
   "source": [
    "bpy.types.Object.myFloat = \n",
    "    bpy.props.FloatVectorProperty(\n",
    "        name = 'floats', \n",
    "        size = 10\n",
    "    )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ee40a9eb",
   "metadata": {},
   "outputs": [],
   "source": [
    "# subtype  可定义 color 欧拉角 向量 等类型属性\n",
    "bpy.types.Object.floatArray = \n",
    "    bpy.props.FloatVectorProperty(\n",
    "        name = 'floats',\n",
    "        subtype = 'COLOR',\n",
    "        size = 3\n",
    "    )"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bbf23bcc",
   "metadata": {},
   "source": [
    "#### 高级操作 -- 键值对 Collection"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b2824a15",
   "metadata": {},
   "source": [
    "主要是弥补VECTOR无法动态扩充 存量少的缺点"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "65f9f957",
   "metadata": {},
   "outputs": [],
   "source": [
    "bpy.props.CollectionProperty()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "81d7bb80",
   "metadata": {},
   "outputs": [],
   "source": [
    "class ClassName(bpy.types.PropertyGroup):\n",
    "    name : \n",
    "        bpy.props.StringProperty\n",
    "        (name = 'name',default = 'None')\n",
    "\n",
    "bpy.utils.register_class(ClassName)       \n",
    "        \n",
    "bpy.types.Object.myProps =\n",
    "    bpy.props.CollectionProperty(type=type(ClassName))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "71e2591e",
   "metadata": {},
   "outputs": [],
   "source": [
    "#定义键值对结构\n",
    "class Gangster(bpy.types.PropertyGroup):\n",
    "    name : bpy.props.StringProperty(name = 'name',default = 'None')\n",
    "    age  : bpy.props.IntProperty   (name = 'age' ,default = 18 )\n",
    "    sex  : bpy.props.StringProperty(name = 'sex' ,default = 'woman')\n",
    "#类注册\n",
    "bpy.utils.register_class(Gangster)\n",
    "#新建键值对属性\n",
    "bpy.types.Object.gangster \n",
    "    = bpy.props.CollectionProperty(type = Gangster) \n",
    "#获得某个部件\n",
    "cube = bpy.data.objects['Cube'] \n",
    "#在键值对属性列表中新增一行数据  \n",
    "borrower = cube.gangster.add()\n",
    "#对键值对属性赋值\n",
    "borrower.name = 'name1'\n",
    "borrower.age = 15\n",
    "borrower.sex = \"man\" "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7dab9cb7",
   "metadata": {},
   "outputs": [],
   "source": [
    "#删除属性\n",
    "for borrower in cube.gangster:\n",
    "    del borrower['age']\n",
    "    del borrower['name']\n",
    "    del borrower['sex']"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "37de640b",
   "metadata": {},
   "source": [
    "#### 高级操作 -- 结构体\n",
    "\n",
    "结构体只能一次存储一个数据组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1c1661a2",
   "metadata": {},
   "outputs": [],
   "source": [
    "bpy.props.PointerProperty()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3e2d7e17",
   "metadata": {},
   "outputs": [],
   "source": [
    "#定义结构体\n",
    "class MaterialSettings(bpy.types.PropertyGroup):\n",
    "    my_int:bpy.props.IntProperty()\n",
    "    my_float:bpy.props.FloatProperty()\n",
    "    my_string:bpy.props.StringProperty()\n",
    "#类注册\n",
    "bpy.utils.register_class(MaterialSettings)\n",
    "#新建结构体属性\n",
    "bpy.types.Material.my_settings \n",
    "    = bpy.props.PointerProperty(type=MaterialSettings)\n",
    "#赋值\n",
    "material = bpy.types.Material[0]\n",
    "material.my_settings.mu_int= 5\n",
    "material.my_settings.my_float= 3.2\n",
    "material.my_settings.my_string= 'Fo'"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "339707a1",
   "metadata": {},
   "source": [
    "#### 高级操作 -- 三回调 "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0da89c28",
   "metadata": {},
   "source": [
    "三回调\n",
    "- get  在bool int float string enum 使用\n",
    "- set  在bool int float string enum 使用\n",
    "- update 在bool int float string enum  pointer 使用\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "56573a84",
   "metadata": {},
   "outputs": [],
   "source": [
    "#get set 用法\n",
    "#get set 用于 每次调用 属性时运行\n",
    "\n",
    "def mySet(self,value):\n",
    "    self['val'] = value\n",
    "    print('set:'+ str(value))\n",
    "\n",
    "def myGet(self):\n",
    "    print('get:' )\n",
    "    return self['val']  #该项需要在上述set内先运行产生\n",
    "     \n",
    "bpy.types.Object.myFloat = bpy.props.FloatProperty(\n",
    "    name = 'float',\n",
    "    set = mySet, \n",
    "    get = myGet\n",
    ") "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d4199957",
   "metadata": {},
   "outputs": [],
   "source": [
    "#update  改变数据时  界面会同步更新\n",
    "\n",
    "def myUpdate(self,context):\n",
    "    # cube = context.scene.objects['Cube']\n",
    "    cube = context.object\n",
    "    cube.location[0] = self.myFloat\n",
    "    print('val:'+ str(self.myFloat))\n",
    "    \n",
    "bpy.types.Object.myFloat = bpy.props.FloatProperty(\n",
    "    name = 'float',\n",
    "    update = myUpdate \n",
    ")  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "423c7d0a",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "18cf2367",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "680af6ea",
   "metadata": {},
   "source": [
    "### 6. 模块 bpy.utils"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "32e30354",
   "metadata": {},
   "source": [
    "blender 自身的工具 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5592387a",
   "metadata": {},
   "outputs": [],
   "source": [
    "bpy.utils.register_class()\n",
    "bpy.utils.unregister_class()\n",
    "#常用于 blender插件注册时对类做注册"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9bed95d9",
   "metadata": {},
   "outputs": [],
   "source": [
    "#此处为第零章的测试代码段\n",
    "\n",
    "#在blender SDK加载界面选择加载和取消加载时的动作\n",
    "# 加载 和 卸载 插件时 注册 和 解注册\n",
    "def register():\n",
    "    bpy.utils.register_class()\n",
    "\n",
    "def unregister():\n",
    "    bpy.utils.unregister_class()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "50ef01fa",
   "metadata": {},
   "source": [
    "### 7. 模块 bpy.utils"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6918b7e2",
   "metadata": {},
   "source": [
    "系统文件系统的访问   文件系统路径\n",
    "bpy.path.abspath   \n",
    "bpy.path.basename   \n",
    "bpy.path.relpath\n",
    "使用之前需要保存Blender文件"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "eb10d3ce",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 绝对路径\n",
    "bpy.path.abspath \n",
    "#  'Z:\\\\_PROJECT_\\\\Blender\\\\'\n",
    "\n",
    "#获得文件名\n",
    "bpy.path.basename(\"Z:\\_PROJECT_\\Blender\\test.blend\")\n",
    "# 'test.blend'\n",
    "\n",
    "#获得相对路径\n",
    "bpy.path.relpath(\"Z:\\_PROJECT_\\Blender\\C00\",\n",
    "                 \"Z:\\_PROJECT_\\Blender\")\n",
    "# '//C00' "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "193c4002",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7abd69b2",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "37bad490",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8f42929e",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9018d0c4",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d62b58ae",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
